<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Expression-Based Access Control :: Spring Security</title>
<link rel="canonical" href="../../../servlet/authorization/expression-based.html">
<link rel="prev" href="authorize-requests.html">
<link rel="next" href="secure-objects.html">
<meta name="generator" content="Antora 3.0.0">
<link rel="stylesheet" href="../../../_/css/site.css">
<link href="../../../_/img/favicon.ico" rel='shortcut icon' type='image/vnd.microsoft.icon'>
<link rel="stylesheet" href="../../../_/css/vendor/docsearch.min.css">

<script>var uiRootPath = '../../../_'</script>
</head>
<body class="article">
<header class="header">
<nav class="navbar">
<div class="navbar-brand">
<a class="navbar-item" href="https://spring.io">
<img id="springlogo" class="block" src="../../../_/img/spring-logo.svg" alt="Spring">
</a>
<button class="navbar-burger" data-target="topbar-nav">
<span></span>
<span></span>
<span></span>
</button>
</div>
<div id="topbar-nav" class="navbar-menu">
<div class="navbar-end">
<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link" href="expression-based.html#">Why Spring</a>
<div class="navbar-dropdown">
<a class="navbar-item" href="https://spring.io/why-spring">Overview</a>
<a class="navbar-item" href="https://spring.io/microservices">Microservices</a>
<a class="navbar-item" href="https://spring.io/reactive">Reactive</a>
<a class="navbar-item" href="https://spring.io/event-driven">Event Driven</a>
<a class="navbar-item" href="https://spring.io/cloud">Cloud</a>
<a class="navbar-item" href="https://spring.io/web-applications">Web Applications</a>
<a class="navbar-item" href="https://spring.io/serverless">Serverless</a>
<a class="navbar-item" href="https://spring.io/batch">Batch</a>
</div>
</div>
<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link" href="expression-based.html#">Learn</a>
<div class="navbar-dropdown">
<a class="navbar-item" href="https://spring.io/learn">Overview</a>
<a class="navbar-item" href="https://spring.io/quickstart">Quickstart</a>
<a class="navbar-item" href="https://spring.io/guides">Guides</a>
<a class="navbar-item" href="https://spring.io/blog">Blog</a>
</div>
</div>
<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link" href="expression-based.html#">Projects</a>
<div class="navbar-dropdown">
<a class="navbar-item" href="https://spring.io/projects">Overview</a>
<a class="navbar-item" href="https://spring.io/projects/spring-boot">Spring Boot</a>
<a class="navbar-item" href="https://spring.io/projects/spring-framework">Spring Framework</a>
<a class="navbar-item" href="https://spring.io/projects/spring-cloud">Spring Cloud</a>
<a class="navbar-item" href="https://spring.io/projects/spring-cloud-dataflow">Spring Cloud Data Flow</a>
<a class="navbar-item" href="https://spring.io/projects/spring-data">Spring Data</a>
<a class="navbar-item" href="https://spring.io/projects/spring-integration">Spring Integration</a>
<a class="navbar-item" href="https://spring.io/projects/spring-batch">Spring Batch</a>
<a class="navbar-item" href="https://spring.io/projects/spring-security">Spring Security</a>
<a class="navbar-item navbar-item-special" href="https://spring.io/projects">View all projects</a>
<a class="navbar-item" href="https://spring.io/tools">Spring Tools 4</a>
<a class="navbar-item navbar-item-special-2" href="https://start.spring.io">Spring Initializr <svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><polyline points="15 10.94 15 15 1 15 1 1 5.06 1" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="2"></polyline><polyline points="8.93 1 15 1 15 7.07" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="2"></polyline><line x1="15" y1="1" x2="8" y2="8" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="2"></line></svg></a>
</div>
</div>
<a class="navbar-item" href="https://spring.io/training">Training</a>
<a class="navbar-item" href="https://spring.io/support">Support</a>
<div class="navbar-item has-dropdown is-hoverable is-community">
<a class="navbar-link" href="expression-based.html#">Community</a>
<div class="navbar-dropdown">
<a class="navbar-item" href="https://spring.io/community">Overview</a>
<a class="navbar-item" href="https://spring.io/events">Events</a>
<a class="navbar-item" href="https://spring.io/team">Team</a>
</div>
</div>
</div>
</div>
<div id="switch-theme">
<input type="checkbox" id="switch-theme-checkbox" />
<label for="switch-theme-checkbox">Dark Theme</label>
</div>
</nav>
</header>
<div class="body">
<div class="nav-container" data-component="ROOT" data-version="5.6.0-RC1">
<aside class="nav">
<div class="panels">
<div class="nav-panel-menu is-active" data-panel="menu">
<nav class="nav-menu">
<h3 class="title"><a href="../../index.html">Spring Security</a></h3>
<ul class="nav-list">
<li class="nav-item" data-depth="0">
<ul class="nav-list">
<li class="nav-item" data-depth="1">
<a class="nav-link" href="../../index.html">Overview</a>
</li>
<li class="nav-item" data-depth="1">
<a class="nav-link" href="../../prerequisites.html">Prerequisites</a>
</li>
<li class="nav-item" data-depth="1">
<a class="nav-link" href="../../community.html">Community</a>
</li>
<li class="nav-item" data-depth="1">
<a class="nav-link" href="../../whats-new.html">What&#8217;s New</a>
</li>
<li class="nav-item" data-depth="1">
<a class="nav-link" href="../../getting-spring-security.html">Getting Spring Security</a>
</li>
<li class="nav-item" data-depth="1">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../features/index.html">Features</a>
<ul class="nav-list">
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../features/authentication/index.html">Authentication</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../features/authentication/password-storage.html">Password Storage</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../features/exploits/index.html">Protection Against Exploits</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../features/exploits/csrf.html">CSRF</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../features/exploits/headers.html">HTTP Headers</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../features/exploits/http.html">HTTP Requests</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../features/integrations/index.html">Integrations</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../features/integrations/cryptography.html">Cryptography</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../features/integrations/data.html">Spring Data</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../features/integrations/concurrency.html">Java&#8217;s Concurrency APIs</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../features/integrations/jackson.html">Jackson</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../features/integrations/localization.html">Localization</a>
</li>
</ul>
</li>
</ul>
</li>
<li class="nav-item" data-depth="1">
<a class="nav-link" href="../../modules.html">Project Modules</a>
</li>
<li class="nav-item" data-depth="1">
<a class="nav-link" href="../../samples.html">Samples</a>
</li>
<li class="nav-item" data-depth="1">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../index.html">Servlet Applications</a>
<ul class="nav-list">
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../getting-started.html">Getting Started</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../architecture.html">Architecture</a>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../authentication/index.html">Authentication</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../authentication/architecture.html">Authentication Architecture</a>
</li>
<li class="nav-item" data-depth="3">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../authentication/passwords/index.html">Username/Password</a>
<ul class="nav-list">
<li class="nav-item" data-depth="4">
<button class="nav-item-toggle"></button>
<span class="nav-text">Reading Username/Password</span>
<ul class="nav-list">
<li class="nav-item" data-depth="5">
<a class="nav-link" href="../authentication/passwords/form.html">Form</a>
</li>
<li class="nav-item" data-depth="5">
<a class="nav-link" href="../authentication/passwords/basic.html">Basic</a>
</li>
<li class="nav-item" data-depth="5">
<a class="nav-link" href="../authentication/passwords/digest.html">Digest</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="4">
<button class="nav-item-toggle"></button>
<span class="nav-text">Password Storage</span>
<ul class="nav-list">
<li class="nav-item" data-depth="5">
<a class="nav-link" href="../authentication/passwords/in-memory.html">In Memory</a>
</li>
<li class="nav-item" data-depth="5">
<a class="nav-link" href="../authentication/passwords/jdbc.html">JDBC</a>
</li>
<li class="nav-item" data-depth="5">
<a class="nav-link" href="../authentication/passwords/user-details.html">UserDetails</a>
</li>
<li class="nav-item" data-depth="5">
<a class="nav-link" href="../authentication/passwords/user-details-service.html">UserDetailsService</a>
</li>
<li class="nav-item" data-depth="5">
<a class="nav-link" href="../authentication/passwords/password-encoder.html">PasswordEncoder</a>
</li>
<li class="nav-item" data-depth="5">
<a class="nav-link" href="../authentication/passwords/dao-authentication-provider.html">DaoAuthenticationProvider</a>
</li>
<li class="nav-item" data-depth="5">
<a class="nav-link" href="../authentication/passwords/ldap.html">LDAP</a>
</li>
</ul>
</li>
</ul>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../authentication/session-management.html">Session Management</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../authentication/rememberme.html">Remember Me</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../authentication/openid.html">OpenID</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../authentication/anonymous.html">Anonymous</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../authentication/preauth.html">Pre-Authentication</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../authentication/jaas.html">JAAS</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../authentication/cas.html">CAS</a>
</li>
<li class="nav-item" data-depth="3">
 <a class="nav-link" href="../authentication/x509.html">X509</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../authentication/runas.html">Run-As</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../authentication/logout.html">Logout</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../authentication/events.html">Authentication Events</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="index.html">Authorization</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="architecture.html">Authorization Architecture</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="authorize-requests.html">Authorize HTTP Requests</a>
</li>
<li class="nav-item is-current-page" data-depth="3">
<a class="nav-link" href="expression-based.html">Expression-Based Access Control</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="secure-objects.html">Secure Object Implementations</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="method-security.html">Method Security</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="acls.html">Domain Object Security ACLs</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../oauth2/index.html">OAuth2</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../oauth2/oauth2-login.html">OAuth2 Log In</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../oauth2/oauth2-client.html">OAuth2 Client</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../oauth2/oauth2-resourceserver.html">OAuth2 Resource Server</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../saml2/index.html">SAML2</a>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../exploits/index.html">Protection Against Exploits</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../exploits/csrf.html">Cross Site Request Forgery (CSRF) for Servlet Environments</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../exploits/headers.html">Security HTTP Response Headers</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../exploits/http.html">HTTP</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../exploits/firewall.html">HttpFirewall</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../integrations/index.html">Integrations</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../integrations/servlet-api.html">Servlet APIs</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../integrations/mvc.html">Spring MVC</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../integrations/websocket.html">WebSocket</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../integrations/cors.html">Spring&#8217;s CORS Support</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../integrations/jsp-taglibs.html">JSP Taglib</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<span class="nav-text">Configuration</span>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../configuration/java.html">Java Configuration</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../configuration/kotlin.html">Kotlin Configuration</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../configuration/xml-namespace.html">Namespace Configuration</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../test/index.html">Testing</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../test/method.html">Method Security</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../test/mockmvc.html">MockMvc Support</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../appendix/index.html">Appendix</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../appendix/database-schema.html">Database Schemas</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../appendix/namespace.html">XML Namespace</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../appendix/faq.html">FAQ</a>
</li>
</ul>
</li>
</ul>
</li>
<li class="nav-item" data-depth="1">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../reactive/index.html">Reactive Applications</a>
<ul class="nav-list">
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../../reactive/getting-started.html">Getting Started</a>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<span class="nav-text">Authentication</span>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../reactive/authentication/x509.html">X.509 Authentication</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../reactive/authentication/logout.html">Logout</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<span class="nav-text">Authorization</span>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../reactive/authorization/method.html">EnableReactiveMethodSecurity</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../reactive/oauth2/index.html">OAuth2</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../reactive/oauth2/login.html">OAuth 2.0 Login</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../reactive/oauth2/oauth2-client.html">OAuth2 Client</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../reactive/oauth2/resource-server.html">OAuth 2.0 Resource Server</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../reactive/registered-oauth2-authorized-client.html">@RegisteredOAuth2AuthorizedClient</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../reactive/exploits/index.html">Protection Against Exploits</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../reactive/exploits/csrf.html">CSRF</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../reactive/exploits/headers.html">Headers</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../reactive/exploits/http.html">HTTP Requests</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<span class="nav-text">Integrations</span>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../reactive/integrations/cors.html">CORS</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../reactive/integrations/rsocket.html">RSocket</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../reactive/integrations/webclient.html">WebClient</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../../reactive/test.html">Testing</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../../reactive/configuration/webflux.html">WebFlux Security</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
</div>
<div class="nav-panel-explore" data-panel="explore">
<div class="context">
<span class="title">Spring Security</span>
<span class="version">5.6.0-RC1</span>
</div>
<ul class="components">
<li class="component is-current">
<a class="title" href="../../../index.html">Spring Security</a>
<ul class="versions">
<li class="version">
<a href="../../../6.0/index.html">6.0.0-SNAPSHOT</a>
</li>
<li class="version">
<a href="../../../6.0.0-M3/index.html">6.0.0-M3</a>
</li>
<li class="version">
<a href="../../../6.0.0-M2/index.html">6.0.0-M2</a>
</li>
<li class="version">
<a href="../../../6.0.0-M1/index.html">6.0.0-M1</a>
</li>
<li class="version">
<a href="../../../5.7/index.html">5.7.0-SNAPSHOT</a>
</li>
<li class="version">
<a href="../../../5.7.0-RC1/index.html">5.7.0-RC1</a>
</li>
<li class="version">
<a href="../../../5.7.0-M3/index.html">5.7.0-M3</a>
</li>
<li class="version">
<a href="../../../5.7.0-M2/index.html">5.7.0-M2</a>
</li>
<li class="version">
<a href="../../../5.7.0-M1/index.html">5.7.0-M1</a>
</li>
<li class="version">
<a href="../../../5.6.4/index.html">5.6.4-SNAPSHOT</a>
</li>
<li class="version is-latest">
<a href="../../../index.html">5.6.3</a>
</li>
<li class="version">
<a href="../../../5.6.2/index.html">5.6.2</a>
</li>
<li class="version">
<a href="../../../5.6.1/index.html">5.6.1</a>
</li>
<li class="version">
<a href="../../../5.6.0/index.html">5.6.0</a>
</li>
<li class="version is-current">
<a href="../../index.html">5.6.0-RC1</a>
</li>
</ul>
</li>
</ul>
</div>
</div>
</aside>
</div>
<main class="article">
<div class="toolbar" role="navigation">
<button class="nav-toggle"></button>
<nav class="breadcrumbs" aria-label="breadcrumbs">
<ul>
<li><a href="../../index.html">Spring Security</a></li>
<li><a href="../index.html">Servlet Applications</a></li>
<li><a href="index.html">Authorization</a></li>
<li><a href="expression-based.html">Expression-Based Access Control</a></li>
</ul>
</nav>
<div class="search">
<input id="search-input" type="text" placeholder="Search docs">
</div>
<div class="page-versions">
<button class="version-menu-toggle" title="Show other versions of page">5.6.0-RC1</button>
<div class="version-menu">
<a class="version" href="../../../6.0/servlet/authorization/expression-based.html">6.0.0-SNAPSHOT</a>
<a class="version" href="../../../6.0.0-M3/servlet/authorization/expression-based.html">6.0.0-M3</a>
<a class="version" href="../../../6.0.0-M2/servlet/authorization/expression-based.html">6.0.0-M2</a>
<a class="version" href="../../../6.0.0-M1/servlet/authorization/expression-based.html">6.0.0-M1</a>
<a class="version" href="../../../5.7/servlet/authorization/expression-based.html">5.7.0-SNAPSHOT</a>
<a class="version" href="../../../5.7.0-RC1/servlet/authorization/expression-based.html">5.7.0-RC1</a>
<a class="version" href="../../../5.7.0-M3/servlet/authorization/expression-based.html">5.7.0-M3</a>
<a class="version" href="../../../5.7.0-M2/servlet/authorization/expression-based.html">5.7.0-M2</a>
<a class="version" href="../../../5.7.0-M1/servlet/authorization/expression-based.html">5.7.0-M1</a>
<a class="version" href="../../../5.6.4/servlet/authorization/expression-based.html">5.6.4-SNAPSHOT</a>
<a class="version" href="../../../servlet/authorization/expression-based.html">5.6.3</a>
<a class="version" href="../../../5.6.2/servlet/authorization/expression-based.html">5.6.2</a>
<a class="version" href="../../../5.6.1/servlet/authorization/expression-based.html">5.6.1</a>
<a class="version" href="../../../5.6.0/servlet/authorization/expression-based.html">5.6.0</a>
<a class="version is-current" href="expression-based.html">5.6.0-RC1</a>
</div>
</div>
<div class="edit-this-page"><a href="https://github.com/spring-projects/spring-security/blob/5.6.0-RC1/docs/modules/ROOT/pages/servlet/authorization/expression-based.adoc">Edit this Page</a></div>
</div>
<div class="content">
<aside class="toc sidebar" data-title="Contents" data-levels="2">
<div class="toc-menu"></div>
</aside>
<article class="doc">
<div class="admonitionblock important">
<table>
<tbody><tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
<div class="paragraph">
<p> For the latest stable version, please use <a href="../../../servlet/authorization/expression-based.html">Spring Security 5.6.3</a>!</p>
</div>
</td>
</tr></tbody>
</table>
</div>
<h1 id="page-title" class="page">Expression-Based Access Control</h1>
<div class="sect1">
<h2 id="_overview"><a class="anchor" href="expression-based.html#_overview"></a>Overview</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Spring Security uses Spring EL for expression support and you should look at how that works if you are interested in understanding the topic in more depth.
Expressions are evaluated with a "root object" as part of the evaluation context.
Spring Security uses specific classes for web and method security as the root object, in order to provide built-in expressions and access to values such as the current principal.</p>
</div>
<div class="sect2">
<h3 id="el-common-built-in"><a class="anchor" href="expression-based.html#el-common-built-in"></a>Common Built-In Expressions</h3>
<div class="paragraph">
<p>The base class for expression root objects is <code>SecurityExpressionRoot</code>.
This provides some common expressions which are available in both web and method security.</p>
</div>
<table id="common-expressions" class="tableblock frame-all grid-all stretch">
<caption class="title">Table 1. Common built-in expressions</caption>
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Expression</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>hasRole(String role)</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <code>true</code> if the current principal has the specified role.</p>
<p class="tableblock">For example, <code>hasRole('admin')</code></p>
<p class="tableblock">By default if the supplied role does not start with 'ROLE_' it will be added.
This can be customized by modifying the <code>defaultRolePrefix</code> on <code>DefaultWebSecurityExpressionHandler</code>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>hasAnyRole(String&#8230;&#8203; roles)</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <code>true</code> if the current principal has any of the supplied roles (given as a comma-separated list of strings).</p>
<p class="tableblock">For example, <code>hasAnyRole('admin', 'user')</code></p>
<p class="tableblock">By default if the supplied role does not start with 'ROLE_' it will be added.
This can be customized by modifying the <code>defaultRolePrefix</code> on <code>DefaultWebSecurityExpressionHandler</code>.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>hasAuthority(String authority)</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <code>true</code> if the current principal has the specified authority.</p>
<p class="tableblock">For example, <code>hasAuthority('read')</code></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>hasAnyAuthority(String&#8230;&#8203; authorities)</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <code>true</code> if the current principal has any of the supplied authorities (given as a comma-separated list of strings)</p>
<p class="tableblock">For example, <code>hasAnyAuthority('read', 'write')</code></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>principal</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Allows direct access to the principal object representing the current user</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>authentication</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Allows direct access to the current <code>Authentication</code> object obtained from the <code>SecurityContext</code></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>permitAll</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Always evaluates to <code>true</code></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>denyAll</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Always evaluates to <code>false</code></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>isAnonymous()</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <code>true</code> if the current principal is an anonymous user</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>isRememberMe()</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <code>true</code> if the current principal is a remember-me user</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>isAuthenticated()</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <code>true</code> if the user is not anonymous</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>isFullyAuthenticated()</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <code>true</code> if the user is not an anonymous or a remember-me user</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>hasPermission(Object target, Object permission)</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <code>true</code> if the user has access to the provided target for the given permission.
For example, <code>hasPermission(domainObject, 'read')</code></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>hasPermission(Object targetId, String targetType, Object permission)</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Returns <code>true</code> if the user has access to the provided target for the given permission.
For example, <code>hasPermission(1, 'com.example.domain.Message', 'read')</code></p></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="el-access-web"><a class="anchor" href="expression-based.html#el-access-web"></a>Web Security Expressions</h2>
<div class="sectionbody">
<div class="paragraph">
<p>To use expressions to secure individual URLs, you would first need to set the <code>use-expressions</code> attribute in the <code>&lt;http&gt;</code> element to <code>true</code>.
Spring Security will then expect the <code>access</code> attributes of the <code>&lt;intercept-url&gt;</code> elements to contain Spring EL expressions.
The expressions should evaluate to a Boolean, defining whether access should be allowed or not.
For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-xml hljs" data-lang="xml">&lt;http&gt;
	&lt;intercept-url pattern="/admin*"
		access="hasRole('admin') and hasIpAddress('192.168.1.0/24')"/&gt;
	...
&lt;/http&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Here we have defined that the "admin" area of an application (defined by the URL pattern) should only be available to users who have the granted authority "admin" and whose IP address matches a local subnet.
We&#8217;ve already seen the built-in <code>hasRole</code> expression in the previous section.
The expression <code>hasIpAddress</code> is an additional built-in expression which is specific to web security.
It is defined by the <code>WebSecurityExpressionRoot</code> class, an instance of which is used as the expression root object when evaluating web-access expressions.
This object also directly exposed the <code>HttpServletRequest</code> object under the name <code>request</code> so you can invoke the request directly in an expression.
If expressions are being used, a <code>WebExpressionVoter</code> will be added to the <code>AccessDecisionManager</code> which is used by the namespace.
So if you aren&#8217;t using the namespace and want to use expressions, you will have to add one of these to your configuration.</p>
</div>
<div class="sect2">
<h3 id="el-access-web-beans"><a class="anchor" href="expression-based.html#el-access-web-beans"></a>Referring to Beans in Web Security Expressions</h3>
<div class="paragraph">
<p>If you wish to extend the expressions that are available, you can easily refer to any Spring Bean you expose.
For example, assuming you have a Bean with the name of <code>webSecurity</code> that contains the following method signature:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">public class WebSecurity {
		public boolean check(Authentication authentication, HttpServletRequest request) {
				...
		}
}</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">class WebSecurity {
    fun check(authentication: Authentication?, request: HttpServletRequest?): Boolean {
        // ...
    }
}</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>You could refer to the method using:</p>
</div>
<div class="exampleblock">
<div class="title">Example 1. Refer to method</div>
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">http
    .authorizeRequests(authorize -&gt; authorize
        .antMatchers("/user/**").access("@webSecurity.check(authentication,request)")
        ...
    )</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">XML</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-xml hljs" data-lang="xml">&lt;http&gt;
	&lt;intercept-url pattern="/user/**"
		access="@webSecurity.check(authentication,request)"/&gt;
	...
&lt;/http&gt;</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">http {
    authorizeRequests {
        authorize("/user/**", "@webSecurity.check(authentication,request)")
    }
}</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="el-access-web-path-variables"><a class="anchor" href="expression-based.html#el-access-web-path-variables"></a>Path Variables in Web Security Expressions</h3>
<div class="paragraph">
<p>At times it is nice to be able to refer to path variables within a URL.
For example, consider a RESTful application that looks up a user by id from the URL path in the format <code>/user/{userId}</code>.</p>
</div>
<div class="paragraph">
<p>You can easily refer to the path variable by placing it in the pattern.
For example, if you had a Bean with the name of <code>webSecurity</code> that contains the following method signature:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">public class WebSecurity {
		public boolean checkUserId(Authentication authentication, int id) {
				...
		}
}</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">class WebSecurity {
    fun checkUserId(authentication: Authentication?, id: Int): Boolean {
        // ...
    }
}</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>You could refer to the method using:</p>
</div>
<div class="exampleblock">
<div class="title">Example 2. Path Variables</div>
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">http
	.authorizeRequests(authorize -&gt; authorize
		.antMatchers("/user/{userId}/**").access("@webSecurity.checkUserId(authentication,#userId)")
		...
	);</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">XML</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-xml hljs" data-lang="xml">&lt;http&gt;
	&lt;intercept-url pattern="/user/{userId}/**"
		access="@webSecurity.checkUserId(authentication,#userId)"/&gt;
	...
&lt;/http&gt;</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">http {
    authorizeRequests {
        authorize("/user/{userId}/**", "@webSecurity.checkUserId(authentication,#userId)")
    }
}</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>In this configuration URLs that match would pass in the path variable (and convert it) into checkUserId method.
For example, if the URL were <code>/user/123/resource</code>, then the id passed in would be <code>123</code>.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_method_security_expressions"><a class="anchor" href="expression-based.html#_method_security_expressions"></a>Method Security Expressions</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Method security is a bit more complicated than a simple allow or deny rule.
Spring Security 3.0 introduced some new annotations in order to allow comprehensive support for the use of expressions.</p>
</div>
<div class="sect2">
<h3 id="el-pre-post-annotations"><a class="anchor" href="expression-based.html#el-pre-post-annotations"></a>@Pre and @Post Annotations</h3>
<div class="paragraph">
<p>There are four annotations which support expression attributes to allow pre and post-invocation authorization checks and also to support filtering of submitted collection arguments or return values.
They are <code>@PreAuthorize</code>, <code>@PreFilter</code>, <code>@PostAuthorize</code> and <code>@PostFilter</code>.
Their use is enabled through the <code>global-method-security</code> namespace element:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-xml hljs" data-lang="xml">&lt;global-method-security pre-post-annotations="enabled"/&gt;</code></pre>
</div>
</div>
<div class="sect3">
<h4 id="_access_control_using_preauthorize_and_postauthorize"><a class="anchor" href="expression-based.html#_access_control_using_preauthorize_and_postauthorize"></a>Access Control using @PreAuthorize and @PostAuthorize</h4>
<div class="paragraph">
<p>The most obviously useful annotation is <code>@PreAuthorize</code> which decides whether a method can actually be invoked or not.
For example (from the <a href="https://github.com/spring-projects/spring-security-samples/tree/main/servlet/xml/java/contacts">Contacts</a> sample application)</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@PreAuthorize("hasRole('USER')")
public void create(Contact contact);</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">@PreAuthorize("hasRole('USER')")
fun create(contact: Contact?)</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>which means that access will only be allowed for users with the role "ROLE_USER".
Obviously the same thing could easily be achieved using a traditional configuration and a simple configuration attribute for the required role.
But what about:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@PreAuthorize("hasPermission(#contact, 'admin')")
public void deletePermission(Contact contact, Sid recipient, Permission permission);</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">@PreAuthorize("hasPermission(#contact, 'admin')")
fun deletePermission(contact: Contact?, recipient: Sid?, permission: Permission?)</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>Here we&#8217;re actually using a method argument as part of the expression to decide whether the current user has the "admin" permission for the given contact.
The built-in <code>hasPermission()</code> expression is linked into the Spring Security ACL module through the application context, as we&#8217;ll <a href="expression-based.html#el-permission-evaluator">see below</a>.
You can access any of the method arguments by name as expression variables.</p>
</div>
<div class="paragraph">
<p>There are a number of ways in which Spring Security can resolve the method arguments.
Spring Security uses <code>DefaultSecurityParameterNameDiscoverer</code> to discover the parameter names.
By default, the following options are tried for a method as a whole.</p>
</div>
<div class="ulist">
<ul>
<li>
<p>If Spring Security&#8217;s <code>@P</code> annotation is present on a single argument to the method, the value will be used.
This is useful for interfaces compiled with a JDK prior to JDK 8 which do not contain any information about the parameter names.
For example:</p>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">import org.springframework.security.access.method.P;

...

@PreAuthorize("#c.name == authentication.name")
public void doSomething(@P("c") Contact contact);</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">import org.springframework.security.access.method.P

...

@PreAuthorize("#c.name == authentication.name")
fun doSomething(@P("c") contact: Contact?)</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>Behind the scenes this is implemented using <code>AnnotationParameterNameDiscoverer</code> which can be customized to support the value attribute of any specified annotation.</p>
</div>
</li>
<li>
<p>If Spring Data&#8217;s <code>@Param</code> annotation is present on at least one parameter for the method, the value will be used.
This is useful for interfaces compiled with a JDK prior to JDK 8 which do not contain any information about the parameter names.
For example:</p>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">import org.springframework.data.repository.query.Param;

...

@PreAuthorize("#n == authentication.name")
Contact findContactByName(@Param("n") String name);</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">import org.springframework.data.repository.query.Param

...

@PreAuthorize("#n == authentication.name")
fun findContactByName(@Param("n") name: String?): Contact?</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>Behind the scenes this is implemented using <code>AnnotationParameterNameDiscoverer</code> which can be customized to support the value attribute of any specified annotation.</p>
</div>
</li>
<li>
<p>If JDK 8 was used to compile the source with the -parameters argument and Spring 4+ is being used, then the standard JDK reflection API is used to discover the parameter names.
This works on both classes and interfaces.</p>
</li>
<li>
<p>Last, if the code was compiled with the debug symbols, the parameter names will be discovered using the debug symbols.
This will not work for interfaces since they do not have debug information about the parameter names.
For interfaces, annotations or the JDK 8 approach must be used.</p>
</li>
</ul>
</div>
<div class="openblock">
<div class="title"><a id="el-pre-post-annotations-spel"></a></div>
<div class="content">
<div class="paragraph">
<p>Any Spring-EL functionality is available within the expression, so you can also access properties on the arguments.
For example, if you wanted a particular method to only allow access to a user whose username matched that of the contact, you could write</p>
</div>
</div>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@PreAuthorize("#contact.name == authentication.name")
public void doSomething(Contact contact);</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">@PreAuthorize("#contact.name == authentication.name")
fun doSomething(contact: Contact?)</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>Here we are accessing another built-in expression, <code>authentication</code>, which is the <code>Authentication</code> stored in the security context.
You can also access its "principal" property directly, using the expression <code>principal</code>.
The value will often be a <code>UserDetails</code> instance, so you might use an expression like <code>principal.username</code> or <code>principal.enabled</code>.</p>
</div>
<div class="openblock">
<div class="title"><a id="el-pre-post-annotations-post"></a></div>
<div class="content">
<div class="paragraph">
<p>Less commonly, you may wish to perform an access-control check after the method has been invoked.
This can be achieved using the <code>@PostAuthorize</code> annotation.
To access the return value from a method, use the built-in name <code>returnObject</code> in the expression.</p>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_filtering_using_prefilter_and_postfilter"><a class="anchor" href="expression-based.html#_filtering_using_prefilter_and_postfilter"></a>Filtering using @PreFilter and @PostFilter</h4>
<div class="paragraph">
<p>Spring Security supports filtering of collections, arrays, maps and streams using expressions.
This is most commonly performed on the return value of a method.
For example:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@PreAuthorize("hasRole('USER')")
@PostFilter("hasPermission(filterObject, 'read') or hasPermission(filterObject, 'admin')")
public List&lt;Contact&gt; getAll();</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">@PreAuthorize("hasRole('USER')")
@PostFilter("hasPermission(filterObject, 'read') or hasPermission(filterObject, 'admin')")
fun getAll(): List&lt;Contact?&gt;</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>When using the <code>@PostFilter</code> annotation, Spring Security iterates through the returned collection or map and removes any elements for which the supplied expression is false.
For an array, a new array instance will be returned containing filtered elements.
The name <code>filterObject</code> refers to the current object in the collection.
In case when a map is used it will refer to the current <code>Map.Entry</code> object which allows one to use <code>filterObject.key</code> or <code>filterObject.value</code> in the expresion.
You can also filter before the method call, using <code>@PreFilter</code>, though this is a less common requirement.
The syntax is just the same, but if there is more than one argument which is a collection type then you have to select one by name using the <code>filterTarget</code> property of this annotation.</p>
</div>
<div class="paragraph">
<p>Note that filtering is obviously not a substitute for tuning your data retrieval queries.
If you are filtering large collections and removing many of the entries then this is likely to be inefficient.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="el-method-built-in"><a class="anchor" href="expression-based.html#el-method-built-in"></a>Built-In Expressions</h3>
<div class="paragraph">
<p>There are some built-in expressions which are specific to method security, which we have already seen in use above.
The <code>filterTarget</code> and <code>returnValue</code> values are simple enough, but the use of the <code>hasPermission()</code> expression warrants a closer look.</p>
</div>
<div class="sect3">
<h4 id="el-permission-evaluator"><a class="anchor" href="expression-based.html#el-permission-evaluator"></a>The PermissionEvaluator interface</h4>
<div class="paragraph">
<p><code>hasPermission()</code> expressions are delegated to an instance of <code>PermissionEvaluator</code>.
It is intended to bridge between the expression system and Spring Security&#8217;s ACL system, allowing you to specify authorization constraints on domain objects, based on abstract permissions.
It has no explicit dependencies on the ACL module, so you could swap that out for an alternative implementation if required.
The interface has two methods:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">boolean hasPermission(Authentication authentication, Object targetDomainObject,
							Object permission);

boolean hasPermission(Authentication authentication, Serializable targetId,
							String targetType, Object permission);</code></pre>
</div>
</div>
<div class="paragraph">
<p>which map directly to the available versions of the expression, with the exception that the first argument (the <code>Authentication</code> object) is not supplied.
The first is used in situations where the domain object, to which access is being controlled, is already loaded.
Then expression will return true if the current user has the given permission for that object.
The second version is used in cases where the object is not loaded, but its identifier is known.
An abstract "type" specifier for the domain object is also required, allowing the correct ACL permissions to be loaded.
This has traditionally been the Java class of the object, but does not have to be as long as it is consistent with how the permissions are loaded.</p>
</div>
<div class="paragraph">
<p>To use <code>hasPermission()</code> expressions, you have to explicitly configure a <code>PermissionEvaluator</code> in your application context.
This would look something like this:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-xml hljs" data-lang="xml">&lt;security:global-method-security pre-post-annotations="enabled"&gt;
&lt;security:expression-handler ref="expressionHandler"/&gt;
&lt;/security:global-method-security&gt;

&lt;bean id="expressionHandler" class=
"org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler"&gt;
	&lt;property name="permissionEvaluator" ref="myPermissionEvaluator"/&gt;
&lt;/bean&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Where <code>myPermissionEvaluator</code> is the bean which implements <code>PermissionEvaluator</code>.
Usually this will be the implementation from the ACL module which is called <code>AclPermissionEvaluator</code>.
See the <a href="https://github.com/spring-projects/spring-security-samples/tree/main/servlet/xml/java/contacts">Contacts</a> sample application configuration for more details.</p>
</div>
</div>
<div class="sect3">
<h4 id="_method_security_meta_annotations"><a class="anchor" href="expression-based.html#_method_security_meta_annotations"></a>Method Security Meta Annotations</h4>
<div class="paragraph">
<p>You can make use of meta annotations for method security to make your code more readable.
This is especially convenient if you find that you are repeating the same complex expression throughout your code base.
For example, consider the following:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@PreAuthorize("#contact.name == authentication.name")</code></pre>
</div>
</div>
<div class="paragraph">
<p>Instead of repeating this everywhere, we can create a meta annotation that can be used instead.</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@Retention(RetentionPolicy.RUNTIME)
@PreAuthorize("#contact.name == authentication.name")
public @interface ContactPermission {}</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">@Retention(AnnotationRetention.RUNTIME)
@PreAuthorize("#contact.name == authentication.name")
annotation class ContactPermission</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>Meta annotations can be used for any of the Spring Security method security annotations.
In order to remain compliant with the specification JSR-250 annotations do not support meta annotations.</p>
</div>
</div>
</div>
</div>
</div>
<nav class="pagination">
<span class="prev"><a href="authorize-requests.html">Authorize HTTP Requests</a></span>
<span class="next"><a href="secure-objects.html">Secure Object Implementations</a></span>
</nav>
</article>
</div>
</main>
</div>
<footer class="footer flex">
<div id="spring-links flex">
<img id="springlogo" src="../../../_/img/spring-logo.svg" alt="Spring">
<p class="smallest antialiased">© <script>var d = new Date();
        document.write(d.getFullYear());</script> <a href="https://www.vmware.com/">VMware</a>, Inc. or its affiliates. <a href="https://www.vmware.com/help/legal.html">Terms of Use</a> • <a href="https://www.vmware.com/help/privacy.html" rel="noopener noreferrer">Privacy</a> • <a href="https://spring.io/trademarks">Trademark Guidelines</a> <span id="thank-you-mobile">• <a href="https://spring.io/thank-you">Thank you</a></span> • <a href="https://www.vmware.com/help/privacy/california-privacy-rights.html">Your California Privacy Rights</a> • <a class="ot-sdk-show-settings">Cookie Settings</a> <span id="teconsent"></span></p>
<p class="smallest antialiased">Apache®, Apache Tomcat®, Apache Kafka®, Apache Cassandra&trade;, and Apache Geode&trade; are trademarks or registered trademarks of the Apache Software Foundation in the United States and/or other countries. Java&trade;, Java&trade; SE, Java&trade; EE, and OpenJDK&trade; are trademarks of Oracle and/or its affiliates. Kubernetes® is a registered trademark of the Linux Foundation in the United States and other countries. Linux® is the registered trademark of Linus Torvalds in the United States and other countries. Windows® and Microsoft® Azure are registered trademarks of Microsoft Corporation. “AWS” and “Amazon Web Services” are trademarks or registered trademarks of Amazon.com Inc. or its affiliates. All other trademarks and copyrights are property of their respective owners and are only mentioned for informative purposes. Other names may be trademarks of their respective owners.</p>
</div>
<div id="social-icons" class="flex jc-between">
<a href="https://www.youtube.com/user/SpringSourceDev" title="Youtube"><svg id="youtube-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40"><circle class="cls-1" cx="20" cy="20" r="20" /><path class="cls-2" d="M30.91,14.53a2.89,2.89,0,0,0-2-2C27.12,12,20,12,20,12s-7.12,0-8.9.47a2.9,2.9,0,0,0-2,2A30.56,30.56,0,0,0,8.63,20a30.44,30.44,0,0,0,.46,5.47,2.89,2.89,0,0,0,2,2C12.9,28,20,28,20,28s7.12,0,8.9-.47a2.87,2.87,0,0,0,2-2A30.56,30.56,0,0,0,31.37,20,28.88,28.88,0,0,0,30.91,14.53ZM17.73,23.41V16.59L23.65,20Z" /></svg></a>
<a href="https://github.com/spring-projects" title="Github"><svg id="github-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 75.93 75.93"><path class="cls-1" d="M38,0a38,38,0,1,0,38,38A38,38,0,0,0,38,0Z" /></g><path class="cls-2" d="M38,15.59A22.95,22.95,0,0,0,30.71,60.3c1.15.21,1.57-.5,1.57-1.11s0-2,0-3.9c-6.38,1.39-7.73-3.07-7.73-3.07A6.09,6.09,0,0,0,22,48.86c-2.09-1.42.15-1.39.15-1.39a4.81,4.81,0,0,1,3.52,2.36c2,3.5,5.37,2.49,6.67,1.91a4.87,4.87,0,0,1,1.46-3.07c-5.09-.58-10.45-2.55-10.45-11.34a8.84,8.84,0,0,1,2.36-6.15,8.29,8.29,0,0,1,.23-6.07s1.92-.62,6.3,2.35a21.82,21.82,0,0,1,11.49,0c4.38-3,6.3-2.35,6.3-2.35a8.29,8.29,0,0,1,.23,6.07,8.84,8.84,0,0,1,2.36,6.15c0,8.81-5.37,10.75-10.48,11.32a5.46,5.46,0,0,1,1.56,4.25c0,3.07,0,5.54,0,6.29s.42,1.33,1.58,1.1A22.94,22.94,0,0,0,38,15.59Z" /></svg></a>
<a href="https://twitter.com/springcentral" title="Twitter"><svg id="twitter-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 75.93 75.93"><circle class="cls-1" cx="37.97" cy="37.97" r="37.97" /><path id="Twitter-2" data-name="Twitter" class="cls-2" d="M55.2,22.73a15.43,15.43,0,0,1-4.88,1.91,7.56,7.56,0,0,0-5.61-2.49A7.78,7.78,0,0,0,37,30a7.56,7.56,0,0,0,.2,1.79,21.63,21.63,0,0,1-15.84-8.23,8,8,0,0,0,2.37,10.52,7.66,7.66,0,0,1-3.48-1v.09A7.84,7.84,0,0,0,26.45,41a7.54,7.54,0,0,1-2,.28A7.64,7.64,0,0,1,23,41.09a7.71,7.71,0,0,0,7.18,5.47,15.21,15.21,0,0,1-9.55,3.37,15.78,15.78,0,0,1-1.83-.11,21.41,21.41,0,0,0,11.78,3.54c14.13,0,21.86-12,21.86-22.42,0-.34,0-.68,0-1a15.67,15.67,0,0,0,3.83-4.08,14.9,14.9,0,0,1-4.41,1.24A7.8,7.8,0,0,0,55.2,22.73Z" /></svg></a>
</div>
</footer>
<script src="../../../_/js/site.js"></script>
<script async src="../../../_/js/vendor/highlight.js"></script>
<script async src="../../../_/js/vendor/tabs.js"></script>
<script src="../../../_/js/vendor/switchtheme.js"></script>
<script src="../../../_/js/vendor/docsearch.min.js"></script>

<script>
var search = docsearch({
  appId: '244V8V9FGG',
  apiKey: '82c7ead946afbac3cf98c32446154691',
  indexName: 'security-docs',
  inputSelector: '#search-input',
  autocompleteOptions: { hint: false, keyboardShortcuts: ['s'] },
  algoliaOptions: { hitsPerPage: 10 }
}).autocomplete
search.on('autocomplete:closed', function () { search.autocomplete.setVal() })
</script>
<script>if (window.parent == window) {(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)})(window,document,'script','//www.google-analytics.com/analytics.js','ga');ga('create', 'UA-2728886-23', 'auto', {'siteSpeedSampleRate': 100});ga('send', 'pageview');}</script><script defer src="https://static.cloudflareinsights.com/beacon.min.js/v652eace1692a40cfa3763df669d7439c1639079717194" integrity="sha512-Gi7xpJR8tSkrpF7aordPZQlW2DLtzUlZcumS8dMQjwDHEnw9I7ZLyiOj/6tZStRBGtGgN6ceN6cMH8z7etPGlw==" data-cf-beacon='{"rayId":"702d42927b2e97ee","token":"bffcb8a918ae4755926f76178bfbd26b","version":"2021.12.0","si":100}' crossorigin="anonymous"></script>
</body>
</html>
